﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DataTransferObject;
using DDay.iCal.Components;
using DDay.iCal;
using Engine.ScheduleAlgo;

namespace Engine.TaskPrioritizeAlgo
{
    public class PragmaticPrioritizeTaskListAlgo : IPrioritizeAlgorithm
    {
        const Boolean JUMP_TO_NEXT_BLOCK = true;
        const Boolean MIGHT_JUM = false;
        const Boolean HET_BLOCK = true;
        const Boolean HET_TASK = true;
        static Double ALPHA_DUE_DATE = 0.3;
        static Double BETA_PRIORITY = 0.7;

        public static void setAlphaBeta(Double alpha_DueDate, Double beta_Priority)
        {
            ALPHA_DUE_DATE = alpha_DueDate;
            BETA_PRIORITY = beta_Priority;
        }
        public bool setPriorityParameter(ref DataTransferObject.TaskList taskList, DataTransferObject.SystemConfiguration systemConfiguration, DataTransferObject.PriorityCriteria criteria, ref DataTransferObject.PrioritizeReport report)
        {
            throw new NotImplementedException();
        }

        public void JSKECalculatePriority()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Calculates the dynamic weight.
        /// Dung cho scheduling goi lai moi khi dequeue task ra khoi queu (và thêm tasks mới vào queue nếu có)
        /// </summary>
        /// <param name="queue">The queue: Processing Queue.</param>
        /// <param name="systemConfig">The system config.</param>
        public static Boolean calculateSubsequenceEvent(ref List<Event> listEvent, ref List<TaskForSchedule> queue, SystemConfiguration systemConfig, ref MappedFreeTimeBlock currentBlock, MappedFreeTimeList finalList, Double Offset)
        {
            iCalendar iCal = new iCalendar();
            int countTask = queue.Count;
            //int start, end;
            //int periodTime;
            //int currentDate = currentBlock.Start;

            #region giải thuật cũ
            /*
            List<bool> list1 = new List<bool>();
            for (int i = 0; i < countTask; i++) //for each Task in queue
            {
                //initiate list1
                for (long l = 0; l < mappedFreeTimeList.FreeTimeBlockList.Last().EndDateTime; l++)
                {
                    list1.Add(false);
                }

                start = 0;
                end = 0;
                for (int k = 0; k < mappedFreeTimeList.FreeTimeBlockList.Count; k++) //convert list to array
                {
                    start = (int)(mappedFreeTimeList.FreeTimeBlockList[k].StartDateTime);
                    end = (int)(mappedFreeTimeList.FreeTimeBlockList[k].EndDateTime);
                    for (int j = start; j < end; j++)
                    {
                        list1[j] = true;
                    }
                }

                
                //periodTime = 0;
                //if (currentDate < queue[i].MappedDueDate)
                //{
                //    start = (int)currentDate;
                //    end = (int)queue[i].MappedDueDate;
                //    for (int j = start; j < end; j++)
                //    {
                //        if (list1[(int)j])
                //            periodTime++;
                //    }

                //    //tinh theo Risk ve tre duedate cua cac Task
                //    //queue[i].Weight = (1 - queue[i].RemainTime / (Double)periodTime) * 100 + (Double)queue[i].Priority / 26
                //    //                                  + (Double)queue[i].ProjectID / (Double)systemConfig.TabProjectData.ProjectName.Count * 100;

                //    //task nao cang gan duedate thi lam truoc
                //    queue[i].Weight = queue[i].MappedDueDate - currentDate + queue[i].RemainTime + (Double)queue[i].Priority / 26
                //                                      + (Double)queue[i].ProjectID / (Double)systemConfig.TabProjectData.ProjectName.Count * 100;
                //}
                //else
                //{
                //    periodTime = (int)(currentDate - queue[i].MappedDueDate);

                //    queue[i].Weight = -queue[i].RemainTime - periodTime + (Double)queue[i].Priority / 26
                //                                      + (Double)queue[i].ProjectID / (Double)systemConfig.TabProjectData.ProjectName.Count * 100 - 300;
                //}

            }
            //requeue

            for (int i = 0; i < countTask - 1; i++)
            {
                for (int j = 0; j < countTask - i - 1; j++)
                {
                    if (queue[j].Weight > queue[j + 1].Weight)
                    {
                        Task temp = queue[j];
                        queue[j] = queue[j + 1];
                        queue[j + 1] = temp;
                    }
                }
            }
            */
            #endregion

            #region giải thuật mới
            // sort theo EDD

            queue.Sort(delegate(TaskForSchedule task1, TaskForSchedule task2)
            {
                return task1.MappedDueDate.CompareTo(task2.MappedDueDate);
            });

            // remove Tasks không thỏa minimumTimeSplit trong Block
            for (int i = 0; i < queue.Count; i++)
            {
                if (queue[i].UnSatisfiedMinimumTimeSplit)
                {
                    queue.RemoveAt(i);
                    i--;
                }
            }

            countTask = queue.Count;

            // remove Task nằm ngoài Block
            Double sumTime = 0;
            int m;
            for (m = 0; m < countTask; m++)
            {
                sumTime += queue[m].RemainTime;
                if (sumTime >= currentBlock.End - currentBlock.Start)
                {
                    break;
                }
            }

            if (m < countTask)
            {
                queue.RemoveRange(m + 1, countTask - m - 1);
            }

            if (queue.Count == 0)
            {
                return true;
            }

            countTask = queue.Count;
            if (countTask == 1)
            {
                //List<Event> tempListEvent;
                if (!createEventsFromTaskList(ref listEvent, queue, ref currentBlock, finalList, Offset,systemConfig))
                {
                    return false;
                }


                //for (int i = 0; i < tempListEvent.Count; i++)
                //{
                //    listEvent.Add(tempListEvent[i]);
                //}

                if (currentBlock.Start == currentBlock.End)
                {
                    return true;
                }
            }

            #region đã tính trước rồi, đừng đọc làm gì mất công
            //tính weight
            //for (int i = 0; i < countTask; i++)
            //{
            //    queue[i].Weight = (Double)queue[i].Priority / 26
            //                                          + (Double)(queue[i].ProjectID + 1) / (Double)systemConfig.TabProjectData.ListProjectName.Count * 100 * 100;
            //}
            #endregion

            #region xu ly theo event
            ///////////////////////////////tạo list event
            //tạo event đầu tiên
            //sumTime = 0;

            //Event new1stEvent = iCal.Create<Event>();
            //DateTime StartDateTime = new DateTime();
            //DateTime EndDateTime = new DateTime();
            //StartDateTime = finalList.Offset.AddMinutes(currentBlock.StartDateTime - Offset);
            //EndDateTime = StartDateTime.AddMinutes(queue[0].RemainTime);
            //new1stEvent.DTStart = new DDay.iCal.DataTypes.iCalDateTime(StartDateTime);
            //new1stEvent.DTEnd = new DDay.iCal.DataTypes.iCalDateTime(EndDateTime);
            //result.Add(new1stEvent);

            //for (int i = 1; i < countTask; i++)
            //{
            //    Event newEvent = iCal.Create<Event>();

            //    sumTime += queue[i-1].RemainTime;

            //    StartDateTime = finalList.Offset.AddMinutes(currentBlock.StartDateTime + sumTime - Offset);
            //    EndDateTime = StartDateTime.AddMinutes(queue[i].RemainTime);
            //    newEvent.DTStart = new DDay.iCal.DataTypes.iCalDateTime(StartDateTime);
            //    newEvent.DTEnd = new DDay.iCal.DataTypes.iCalDateTime(EndDateTime);
            //    result.Add(new1stEvent);
            //}
            #endregion

            #region xử lý theo task
            //////////// swap Task dựa theo weight
            //tính tổng remainTime của tất cả Task
            int allTasksRemainTime = 0;
            for (int i = 0; i < countTask; i++)
            {
                allTasksRemainTime += (int)queue[i].RemainTime;
            }

            // chắc chắn không có task nào bị trễ deadline trong Block            
            if (queue[0].MappedDueDate > currentBlock.Start && allTasksRemainTime <= queue[0].MappedDueDate - currentBlock.Start)
            {
                queue.Sort(delegate(TaskForSchedule task1, TaskForSchedule task2)
                {

                    return task2.Weight.CompareTo(task1.Weight);
                });
                if (!createEventsFromTaskList(ref listEvent, queue, ref currentBlock, finalList, Offset,systemConfig))
                {
                    return false;
                }

                //for (int i = 0; i < tempListEvent.Count; i++)
                //{
                //    listEvent.Add(tempListEvent[i]);
                //}

                if (currentBlock.Start == currentBlock.End)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else if (queue.Last().MappedDueDate < currentBlock.Start) //tất cả các task đều trễ, làm theo Priority
            {
                queue.Sort(delegate(TaskForSchedule task1, TaskForSchedule task2)
                {
                    return task2.Weight.CompareTo(task1.Weight);
                });
                if (!createEventsFromTaskList(ref listEvent, queue, ref currentBlock, finalList, Offset, systemConfig))
                {
                    return false;
                }

                //for (int i = 0; i < tempListEvent.Count; i++)
                //{
                //    listEvent.Add(tempListEvent[i]);
                //}

                if (currentBlock.Start == currentBlock.End)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }

            else // có thể có task trễ
            {
                if (!createEventsFromTaskList(ref listEvent, queue, ref currentBlock, finalList, Offset, systemConfig))
                {
                    return false;
                }

                //for (int i = 0; i < tempListEvent.Count; i++)
                //{
                //    listEvent.Add(tempListEvent[i]);
                //}

                if (currentBlock.End == currentBlock.Start)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }


            #endregion

            #endregion
        }

        public bool setPriorityParameter(ref List<TaskForSchedule> taskList, SystemConfiguration systemConfiguration, PriorityCriteria criteria, ref PrioritizeReport report)
        {
            throw new NotImplementedException();
        }

        internal static bool createEventByPriority(ref List<Event> result, ref List<TaskForSchedule> queue, SystemConfiguration systemConfiguration, ref MappedFreeTimeBlock currentBlock, MappedFreeTimeList finalList, double Offset)
        {
            iCalendar iCal = new iCalendar();
            int countTask = queue.Count;

            double currentDate = currentBlock.Start;

            // sort theo priority

            queue.Sort(delegate(TaskForSchedule task1, TaskForSchedule task2)
            {
                return task2.Weight.CompareTo(task1.Weight);
            });

            // remove Tasks không thỏa minimumTimeSplit trong Block
            for (int i = 0; i < queue.Count; i++)
            {
                if (queue[i].UnSatisfiedMinimumTimeSplit)
                {
                    queue.RemoveAt(i);
                    i--;
                }
            }

            countTask = queue.Count;

            if (countTask == 0)
            {
                return JUMP_TO_NEXT_BLOCK;
            }

            return createEventsFromTaskList(ref result, queue, ref currentBlock, finalList, Offset, systemConfiguration);

        }

        internal static bool createEventByDuedate(ref List<Event> result, ref List<TaskForSchedule> queue, SystemConfiguration systemConfiguration, ref MappedFreeTimeBlock currentBlock, MappedFreeTimeList finalList, double Offset)
        {
            iCalendar iCal = new iCalendar();
            int countTask = queue.Count;

            double currentDate = currentBlock.Start;

            // sort theo priority

            queue.Sort(delegate(TaskForSchedule task1, TaskForSchedule task2)
            {
                return task1.MappedDueDate.CompareTo(task2.MappedDueDate);
            });

            // remove Tasks không thỏa minimumTimeSplit trong Block
            for (int i = 0; i < queue.Count; i++)
            {
                if (queue[i].UnSatisfiedMinimumTimeSplit)
                {
                    queue.RemoveAt(i);
                    i--;
                }
            }

            countTask = queue.Count;

            if (countTask == 0)
            {
                return JUMP_TO_NEXT_BLOCK;
            }

            return createEventsFromTaskList(ref result, queue, ref currentBlock, finalList, Offset, systemConfiguration);
        }

        internal static bool createEventByDynamicWeight(ref List<Event> result, ref List<TaskForSchedule> queue, SystemConfiguration systemConfiguration, ref MappedFreeTimeBlock currentBlock, int currentBlockIndex, MappedFreeTimeList finalList, double Offset)
        {
            iCalendar iCal = new iCalendar();
            int countTask = queue.Count;

            #region tính dynamic weight
            int currentDate = currentBlock.Start;
                        
            for (int i = 0; i < countTask; i++) //for each Task in queue
            {                
                int timeSpan = 0;
                for (int j = currentBlockIndex; j < finalList.ListFreeTimeBlock.Count; j++)
                {             
                    //Neu duedate van con ở sau block thì cộng thêm và TimeSpan
                    if(queue[i].MappedDueDate > finalList.ListFreeTimeBlock[j].Start)
                    {
                        //Duyệt xem tất cả các WHID trong FinalListBlock này có thể xếp task đó được không
                        for (int k = 0; k < finalList.ListFreeTimeBlock[j].WorkingHour.Count; k++)
                        {
                            if (finalList.ListFreeTimeBlock[j].WorkingHour[k] == queue[i].WorkingHourID)
                            {
                                //Nếu cắt FinaListBlock
                                if (queue[i].MappedDueDate > finalList.ListFreeTimeBlock[j].Start
                                                                  && queue[i].MappedDueDate < finalList.ListFreeTimeBlock[j].End)
                                {
                                    timeSpan += (int)queue[i].MappedDueDate - finalList.ListFreeTimeBlock[j].Start;
                                }
                                else// Nếu DueDate nằm sau FinaListBlock
                                {
                                    timeSpan += finalList.ListFreeTimeBlock[j].End - finalList.ListFreeTimeBlock[j].Start;
                                }
                            }
                        }
                    }
                    else
                    {
                        break;
                    }
                }

                //công thức weight
                //w = ALPHA * Duedate + BETA * Priority (tổng hợp)
                Double P = 0;
                Double D = 0;
                
                //tính Priority (tổng hợp) 80% được quyết định bở Priority của Task, 20% được quyết định bởi Project
                P = ((1.0 - (Double)queue[i].Priority / 10.0) * 8.0
                         + (1.0 - (Double)(queue[i].ProjectID + 1) / (Double)systemConfiguration.TabProjectData.ListProjectName.Count) * 2.0 ) / 10.0;

                //tính Duedate
                // cần phải tính lại vì D quá gần 1 trong khi P lại khá xa 1 -> khi cộng lại sẽ bị D lấn áp
                if (currentDate < queue[i].MappedDueDate)
                {
                    if(timeSpan != 0)
                    { 
                        //D = (queue[i].RemainTime / (Double)timeSpan) * 100; 
                        D = (Double)((Double)queue[i].RemainTime / (Double)timeSpan); 
                    }
                }
                else //đã trễ rồi D sẽ được tính là tổng thời gian trễ
                {
                    //D = -queue[i].RemainTime + queue[i].MappedDueDate - currentDate;
                    //D chính là tổng thời gian trễ khi làm Task
                    D = queue[i].RemainTime + (currentDate - queue[i].MappedDueDate);
                }

                //tính weight
                queue[i].Weight = ALPHA_DUE_DATE * D + BETA_PRIORITY * P;
            }
            #endregion

            // sort theo weight
            queue.Sort(delegate(TaskForSchedule task1, TaskForSchedule task2)
            {
                return task2.Weight.CompareTo(task1.Weight);
            });

            // remove Tasks không thỏa minimumTimeSplit trong Block
            for (int i = 0; i < queue.Count; i++)
            {
                if (queue[i].UnSatisfiedMinimumTimeSplit)
                {
                    queue.RemoveAt(i);
                    i--;
                }
            }

            countTask = queue.Count;

            if (countTask == 0)
            {
                return JUMP_TO_NEXT_BLOCK;
            }

            return createEventsFromTaskList(ref result, queue, ref currentBlock, finalList, Offset, systemConfiguration);
        }

        private static void addTaskInfoToEvent(TaskForSchedule t, ref Event evt, SystemConfiguration systemConfig)
        {
            evt.AddParameter("taskID", Convert.ToString(t.TaskID));
            evt.AddParameter("taskName", t.Name);
            evt.AddParameter("taskProject", systemConfig.TabProjectData.ListProjectName[t.ProjectID]);
            evt.AddParameter("workingHourName",
                systemConfig.TabWorkingHoursData.ListOfWorkingHourItems[t.WorkingHourID].WorkingHourName);
            evt.AddParameter("taskPriority", Convert.ToString(t.Priority));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="result"></param>
        /// <param name="tasks"></param>
        /// <param name="currentBlock"></param>
        /// <param name="finalList"></param>
        /// <param name="Offset"></param>
        /// <returns></returns>
        private static Boolean createEventsFromTaskList(ref List<Event> result, List<TaskForSchedule> tasks, ref MappedFreeTimeBlock currentBlock, MappedFreeTimeList finalList, Double Offset,SystemConfiguration systemConfig)
        {
            iCalendar iCal = new iCalendar();
            Event new1stEvent = iCal.Create<Event>();
            DateTime StartDateTime = new DateTime();
            DateTime EndDateTime = new DateTime();
            int blockAssign = 0;

            StartDateTime = finalList.Offset.AddMinutes(currentBlock.Start - Offset);
            if (tasks[0].RemainTime >= currentBlock.End - currentBlock.Start)// neu task dau tien lon hon block
            {
                EndDateTime = StartDateTime.AddMinutes(currentBlock.End - currentBlock.Start);

                //check minimumTimeSplit constraint
                blockAssign = (int)EndDateTime.Subtract(StartDateTime).TotalMinutes;

                if (blockAssign < tasks[0].MinimumTimeSplit || tasks[0].RemainTime - blockAssign < tasks[0].MinimumTimeSplit)
                {
                    tasks[0].UnSatisfiedMinimumTimeSplit = true;
                    return MIGHT_JUM;
                }

                if (StartDateTime < tasks[0].ScheduledStartDate)
                {
                    tasks[0].ScheduledStartDate = StartDateTime;
                }
                new1stEvent.DTStart = new DDay.iCal.DataTypes.iCalDateTime(StartDateTime);
                new1stEvent.DTEnd = new DDay.iCal.DataTypes.iCalDateTime(EndDateTime);
                new1stEvent.Summary = tasks[0].Name;
                addTaskInfoToEvent(tasks[0], ref new1stEvent, systemConfig);

                result.Add(new1stEvent);
                // trường hợp này ko cần tính SUMTIME
                tasks[0].RemainTime -= currentBlock.End - currentBlock.Start;
                if (tasks[0].RemainTime == 0)
                {
                    tasks[0].Completed = true;
                    tasks[0].ScheduledEndDate = EndDateTime;
                }
                currentBlock.Start = currentBlock.End;
                return HET_BLOCK;
            }
            else //neu task dau tien nho hon block, tính SUMTIME để cập nhật block
            {
                EndDateTime = StartDateTime.AddMinutes(tasks[0].RemainTime);

                //check minimumTimeSplit constraint
                blockAssign = (int)EndDateTime.Subtract(StartDateTime).TotalMinutes;

                if (blockAssign < tasks[0].MinimumTimeSplit || (tasks[0].RemainTime > blockAssign && tasks[0].RemainTime - blockAssign < tasks[0].MinimumTimeSplit))
                {
                    tasks[0].UnSatisfiedMinimumTimeSplit = true;
                    return MIGHT_JUM;
                }

                if (StartDateTime < tasks[0].ScheduledStartDate)
                {
                    tasks[0].ScheduledStartDate = StartDateTime;
                }
                new1stEvent.DTStart = new DDay.iCal.DataTypes.iCalDateTime(StartDateTime);
                new1stEvent.DTEnd = new DDay.iCal.DataTypes.iCalDateTime(EndDateTime);
                new1stEvent.Summary = tasks[0].Name;
                addTaskInfoToEvent(tasks[0], ref new1stEvent, systemConfig);

                result.Add(new1stEvent);

                //sumTime += tasks[0].RemainTime;
                currentBlock.Start += tasks[0].RemainTime;
                tasks[0].Completed = true;
                tasks[0].RemainTime = 0;
                tasks[0].ScheduledEndDate = EndDateTime;
                if (tasks.Count == 1)
                {
                    return HET_TASK;
                }
            }


            int countTask = tasks.Count;
            for (int i = 1; i < countTask - 1; i++)// Làm tất cả các task ở giữa (tas2-> task kế cuối trừ task cuối)
            {
                Event newEvent = iCal.Create<Event>();
                //sumTime += tasks[i - 1].RemainTime;// SUMTIME đã đc tính ở trên
                StartDateTime = EndDateTime;
                if (tasks[i].RemainTime >= currentBlock.End - currentBlock.Start)// Nếu Task >= block hiện tại
                {
                    EndDateTime = StartDateTime.AddMinutes(currentBlock.End - currentBlock.Start);

                    //check minimumTimeSplit constraint
                    blockAssign = (int)EndDateTime.Subtract(StartDateTime).TotalMinutes;

                    if (blockAssign < tasks[i].MinimumTimeSplit || (tasks[i].RemainTime > blockAssign && tasks[i].RemainTime - blockAssign < tasks[i].MinimumTimeSplit))
                    {
                        tasks[i].UnSatisfiedMinimumTimeSplit = true;
                        return MIGHT_JUM;
                    }

                    if (StartDateTime < tasks[i].ScheduledStartDate)
                    {
                        tasks[i].ScheduledStartDate = StartDateTime;
                    }
                    newEvent.DTStart = new DDay.iCal.DataTypes.iCalDateTime(StartDateTime);
                    newEvent.DTEnd = new DDay.iCal.DataTypes.iCalDateTime(EndDateTime);
                    newEvent.Summary = tasks[i].Name;
                    addTaskInfoToEvent(tasks[i], ref newEvent, systemConfig);

                    result.Add(newEvent);

                    tasks[i].RemainTime -= currentBlock.End - currentBlock.Start;
                    if (tasks[i].RemainTime == 0)
                    {
                        tasks[i].Completed = true;
                        tasks[i].ScheduledEndDate = EndDateTime;
                    }
                    currentBlock.Start = currentBlock.End;
                    return HET_BLOCK;
                }
                else //neu tasks[i] nho hon block
                {
                    EndDateTime = StartDateTime.AddMinutes(tasks[i].RemainTime);

                    //check minimumTimeSplit constraint
                    blockAssign = (int)EndDateTime.Subtract(StartDateTime).TotalMinutes;

                    if (blockAssign < tasks[i].MinimumTimeSplit || (tasks[i].RemainTime > blockAssign && tasks[i].RemainTime - blockAssign < tasks[i].MinimumTimeSplit))
                    {
                        tasks[i].UnSatisfiedMinimumTimeSplit = true;
                        return MIGHT_JUM;
                    }

                    if (StartDateTime < tasks[i].ScheduledStartDate)
                    {
                        tasks[i].ScheduledStartDate = StartDateTime;
                    }
                    newEvent.DTStart = new DDay.iCal.DataTypes.iCalDateTime(StartDateTime);
                    newEvent.DTEnd = new DDay.iCal.DataTypes.iCalDateTime(EndDateTime);
                    newEvent.Summary = tasks[i].Name;

                    currentBlock.Start += tasks[i].RemainTime;
                    tasks[i].RemainTime = 0;
                    tasks[i].Completed = true;
                    tasks[i].ScheduledEndDate = EndDateTime;
                    addTaskInfoToEvent(tasks[i], ref newEvent, systemConfig);

                    result.Add(newEvent);
                }
            }

            //cập nhật tasks cuối
            if (tasks.Last().RemainTime >= currentBlock.End - currentBlock.Start)// task cuối dài hơn phần còn lại của Block
            {
                Event newEvent = iCal.Create<Event>();

                //EndDateTime chỗ này sẽ phải giống với EndDateTime ở vòng lặp trên
                StartDateTime = EndDateTime;
                EndDateTime = StartDateTime.AddMinutes(currentBlock.End - currentBlock.Start);

                //check minimumTimeSplit constraint
                blockAssign = (int)EndDateTime.Subtract(StartDateTime).TotalMinutes;

                if (blockAssign < tasks.Last().MinimumTimeSplit || (tasks.Last().RemainTime > blockAssign && tasks.Last().RemainTime - blockAssign < tasks.Last().MinimumTimeSplit))
                {
                    tasks.Last().UnSatisfiedMinimumTimeSplit = true;
                    return MIGHT_JUM;
                }

                if (StartDateTime < tasks.Last().ScheduledStartDate)
                {
                    tasks.Last().ScheduledStartDate = StartDateTime;
                }
                newEvent.DTStart = new DDay.iCal.DataTypes.iCalDateTime(StartDateTime);
                newEvent.DTEnd = new DDay.iCal.DataTypes.iCalDateTime(EndDateTime);
                newEvent.Summary = tasks.Last().Name;
                addTaskInfoToEvent(tasks.Last(), ref newEvent, systemConfig);

                result.Add(newEvent);
                tasks.Last().RemainTime -= currentBlock.End - currentBlock.Start;
                if (tasks.Last().RemainTime == 0)
                {
                    tasks.Last().Completed = true;
                    tasks.Last().ScheduledEndDate = EndDateTime;
                }
                //sumTime = currentBlock.End - currentBlock.Start;
                currentBlock.Start = currentBlock.End;
                return HET_BLOCK;
            }
            else // task cuối ngắn hơn phần còn lại của Block
            {
                Event newEvent = iCal.Create<Event>();
                //EndDateTime chỗ này sẽ phải giống với EndDateTime ở vòng lặp trên nữa
                StartDateTime = EndDateTime;
                EndDateTime = StartDateTime.AddMinutes(tasks.Last().RemainTime);

                //check minimumTimeSplit constraint
                blockAssign = (int)EndDateTime.Subtract(StartDateTime).TotalMinutes;

                if (blockAssign < tasks.Last().MinimumTimeSplit || (tasks.Last().RemainTime > blockAssign && tasks.Last().RemainTime - blockAssign < tasks.Last().MinimumTimeSplit))
                {
                    tasks.Last().UnSatisfiedMinimumTimeSplit = true;
                    return MIGHT_JUM;
                }

                if (StartDateTime < tasks.Last().ScheduledStartDate)
                {
                    tasks.Last().ScheduledStartDate = StartDateTime;
                }
                newEvent.DTStart = new DDay.iCal.DataTypes.iCalDateTime(StartDateTime);
                newEvent.DTEnd = new DDay.iCal.DataTypes.iCalDateTime(EndDateTime);
                newEvent.Summary = tasks.Last().Name;
                addTaskInfoToEvent(tasks.Last(), ref newEvent, systemConfig);
                
                result.Add(newEvent);

                //sumTime += tasks.Last().RemainTime;
                currentBlock.Start += tasks.Last().RemainTime;
                tasks.Last().RemainTime = 0;
                tasks.Last().Completed = true;
                tasks.Last().ScheduledEndDate = EndDateTime;
                return HET_TASK;
            }
            
        }

        
        
    }
}
